home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
cpp_libs
/
awe2-0_1.lha
/
awe2-0.1
/
Src
/
HardwareContext-ns32k.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-09
|
5KB
|
198 lines
// This may look like C code, but it is really -*- C++ -*-
//
// Copyright (C) 1988 University of Illinois, Urbana, Illinois
// Copyright (C) 1989 University of Colorado, Boulder, Colorado
// Copyright (C) 1990 University of Colorado, Boulder, Colorado
//
// written by Dirk Grunwald (grunwald@foobar.colorado.edu)
//
#include "HardwareContext.h"
#include "HardwareContextP.h"
#include "CpuMultiplexor.h"
#include "Thread.h"
#include "assert.h"
#include <stream.h>
//
// Many machines have the same (or very similar) stack format.
// The 68K & 32K are examples of such machines.
//
// The const *registers* defines the number of additional longwords
// needed on the stack past the last frame pointer. This value needs
// to jibe with the one in HardwareContext-<arch>.s.
//
const long MagicStackMarker = 0x464f4f20; // this says 'FOO '
static const int expectedBytesSavedInContext
= 5 * 4 // data registers
+ 2 * 8; // floating registers
static int numberOfBytesSavedInContext = 0;
static void computeBytesSaved();
HardwareContext::HardwareContext (int check, unsigned size)
{
checkStackLimits = check;
stackBase = 0;
stackEnd = 0;
stackMax = 0;
stackSize = 0;
stackCheck = 0;
stackMallocAt = 0;
if (size > 0) {
stackSize = size;
stackMallocAt = new void *[ stackSize ];
//
// stackBase should point to the first writeable cell of the
// new stack.
//
stackEnd = stackMallocAt;
stackBase = &stackMallocAt[stackSize-1];
}
else {
//
// Have the main process figure out how many registers
// (actually, Quads) are pushed when we save an entire context.
//
computeBytesSaved();
assert( numberOfBytesSavedInContext == expectedBytesSavedInContext );
}
}
HardwareContext::reclaimStack()
{
if ( stackMallocAt ) {
if ( check ) {
mprotect(stackMallocAt, pageSizeInBytes, PROT_READ | PROT_WRITE);
}
free(stackMallocAt);
stackMallocAt = 0;
}
}
void
HardwareContext::magicSwitchTo(HardwareContext *to)
{
asm (" " : : :
"r1", "r2", "r3", "r4", "r5", "r6", "r7",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7");
asm __volatile("sprd fp,%0" : "=g" (fp)) ;
asm __volatile("sprd sp,%0" : "=g" (sp)) ;
//
// I think I have to do it in this order to fetch the proper value
// of 'to' -- however, even here, it's not certain to work.
asm __volatile("lprd sp,%0" : : "g" (to -> sp)) ;
asm __volatile("lprd fp,%0" : : "g" (to -> fp)) ;
}
void
HardwareContext::stackOverflow()
{
register unsigned depth = stackBase - getSp();
if (stackMax < depth) {
stackMax = depth;
}
if ( stackMax >= stackSize ) {
cerr << "\nStack overflow\n";
cerr << " getSp() = " << hex(long(getSp()));
cerr << " and stackBase = " << hex(long(stackBase)) << "\n";
cerr << *this << "\n";
cerr << "Current task is \n";
cerr << *(CurrentThread());
cerr << "\n";
cerr.flush();
}
assert( stackMax < stackSize );
assert( *stackCheck == MagicStackMarker );
}
void
HardwareContext::buildReturnFrame(void *returnThis, voidFuncP returnAddress)
{
//
// To build a thread, we return to the first address of startOff,
// which will use the current FP & SP to build a local context,
// and then call the user main.
//
// startOff needs to have a valid frame. The return address for this
// frame is NULL, since we never exit procedure startOff.
//
stackCheck = (long *) stackBase;
register HardwareContextQuad **stack;
stack = (HardwareContextQuad **) stackBase;
*(stack--) = (HardwareContextQuad *) MagicStackMarker;
*(stack--) = 0; // return address
register HardwareContextQuad **startOffFp = stack;
*(stack--) = 0; // frame pointer
//
// Construct the stack frame that will be used in procedure startOff.
// startOff needs to know the value for *this*, which is passed in
// as the first parameter. It also gets the back-link FP for the
// last frame (build above).
//
*(stack--) = (HardwareContextQuad *) returnThis;
register HardwareContextQuad **nullFp = stack;
//
// FP for previous frame
//
*(stack--) = (HardwareContextQuad *) startOffFp;
//
// Now build the stack frame that is used to return to startOff
//
*(stack--) = (HardwareContextQuad *) returnAddress;
fp = (HardwareContextQuad) stack;
*(stack) = (HardwareContextQuad *) nullFp;
//
// casting to char saves us two insn's
//
char *foo = (char *) stack;
foo -= numberOfBytesSavedInContext;
sp = (HardwareContextQuad) foo;
}
static void computeBytesSaved()
{
//
// Cause all registers to be pushed
//
asm (" " : : :
"r1", "r2", "r3", "r4", "r5", "r6", "r7",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7");
long tempSp;
long tempFp;
asm __volatile("sprd fp,%0" : "=g" (tempFp)) ;
asm __volatile("sprd sp,%0" : "=g" (tempSp)) ;
numberOfBytesSavedInContext = tempFp - tempSp;
}
void
HardwareContext::classPrintOn(ostream& s)
{
s << "[HardwareContext] Stack spans " << hex(long(stackEnd));
s << " to " << hex(long(stackBase));
s << " used is " << (stackMax) << " of " << stackSize << "\n";
s << "[HardwareContext] fp = " << hex(long(fp));
s << " sp = " << hex(long(sp));
long p = *( (long *) fp );
s << " @fp = " << hex(p) << "\n";
}